import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:gold/base/view_model.dart';

import 'config.dart';

/// 描述: 根据ViewModel来决定视图的动画widget
/// 
/// @Author tangzhentao
///  @CreatedTime 20:38 2022/6/17
/// 

class ProviderScaffold<T extends Viewmodel> extends StatefulWidget {
  /// 成功内容widget
  final Widget Function(BuildContext context, T data)? builder;
  /// 正在加载widget
  final Widget Function(BuildContext context)? loadingBuilder;
  /// 空数据widget
  final Widget Function(BuildContext context, StateInfo info)? emptyBuilder;
  /// 错误widget
  final Widget Function(BuildContext context, StateInfo info)? errorBuilder;
  /// 不受PageState状态控制范围的上部Widget
  final Widget Function(BuildContext context, T data)? toplessBuilder;
  /// 不受PageState状态控制范围的底部Widget
  final Widget? Function(BuildContext context, T data)? bottomlessBuilder;
  /// 状态数据
  final T model;
  /// 初始化完成
  final Function(T)? onInit;
  ///过度动画时间：毫秒，如：1000=1秒
  final Duration animationDuration;
  final Function(BuildContext)? appBar;
  final Color? backgroundColor;
  final bool? resizeToAvoidBottomInset;
  final bool canPop;
  final Widget? floatingActionButton;
  /// 主内容背景
  final List<Widget>? backgroundWidgets;

  const ProviderScaffold({
    super.key,
    this.loadingBuilder,
    this.emptyBuilder,
    this.errorBuilder,
    this.toplessBuilder,
    this.bottomlessBuilder,
    required this.model,
    required this.builder,
    this.onInit,
    this.animationDuration = const Duration(milliseconds: 250),
    this.appBar,
    this.backgroundColor,
    this.resizeToAvoidBottomInset,
    this.canPop = true,
    this.floatingActionButton,
    this.backgroundWidgets,
  });

  @override
  ProviderScaffoldState<T> createState() => ProviderScaffoldState<T>();
}

class ProviderScaffoldState<T extends Viewmodel> extends State<ProviderScaffold<T>> {
  @override
  void initState() {
    widget.onInit?.call(widget.model);
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider(
      create: (_) => widget.model,
      child: GestureDetector(
        onTap: () => FocusManager.instance.primaryFocus?.unfocus(),
        child: Builder(
            builder: (ctx) => PopScope(
              canPop: widget.canPop,
              child: Scaffold(
                appBar: widget.appBar?.call(ctx),
                backgroundColor: widget.backgroundColor,
                extendBody: widget.appBar == null,
                resizeToAvoidBottomInset: widget.resizeToAvoidBottomInset,
                body: _contentWidget(ctx),
                floatingActionButton: widget.floatingActionButton,
              ),
            )
        ),
      ),
    );
  }

  Widget? _contentWidget(BuildContext ctx) {
    final body = _body(ctx);
    if (body != null) {
      if (widget.backgroundWidgets?.isNotEmpty == true) {
        return Stack(children: widget.backgroundWidgets!..add(body));
      }
      return body;
    }
    return null;
  }

  /// 在状态控制内，受PageState控制的Widget
  Widget? _body(BuildContext ctx) {
    final model = ctx.read<T>();
    Widget? stateWidget;
    Widget? toplessWidget;
    Widget? bottomlessWidget;
    if (widget.builder != null) {
      switch (ctx.select<T, PageState>((value) => value.state)) {
        case PageState.error:
          stateWidget = widget.errorBuilder?.call(ctx, model.failure) ?? errorWidget(model.failure, model.notSuccessColor, onReLoad: model.onRetry);
        case PageState.loading:
          stateWidget = widget.loadingBuilder?.call(ctx) ?? loadingWidget(backgroundColor: model.notSuccessColor);
        case PageState.empty:
          stateWidget = widget.emptyBuilder?.call(ctx, model.empty) ?? emptyWidget(model.empty, model.notSuccessColor, onClick: model.onReload);
        case PageState.success:
          stateWidget = Selector<T, int>(
            selector: (_, k) => k.successChangedCount,
            builder: (con, _, __) => widget.builder!.call(con, model),
          );
      }
    }
    if (widget.toplessBuilder != null) toplessWidget = widget.toplessBuilder!.call(ctx, ctx.read<T>());
    if (widget.bottomlessBuilder != null) bottomlessWidget = widget.bottomlessBuilder!.call(ctx, ctx.read<T>());
    if (toplessWidget != null && stateWidget != null && bottomlessWidget != null) {
      return Column(
        children: [
          toplessWidget,
          Expanded(child: stateWidget),
          bottomlessWidget,
        ],
      );
    } else {
      if (toplessWidget != null && bottomlessWidget != null) {
        return Column(
          children: [
            toplessWidget,
            bottomlessWidget
          ],
        );
      } else if (toplessWidget != null && stateWidget != null) {
        return Column(children: [
          toplessWidget,
          Expanded(child: stateWidget),
        ]);
      } else if (bottomlessWidget != null && stateWidget != null) {
        return Column(children: [
          Expanded(child: stateWidget),
          bottomlessWidget
        ]);
      } else if (toplessWidget != null) {
        return toplessWidget;
      } else if (bottomlessWidget != null) {
        return bottomlessWidget;
      } else if (stateWidget != null) {
        return stateWidget;
      }
    }
    return null;
  }
}